# -*- encoding:utf-8 -*-

from api.ps import PS
from api.pts import PTS
from resource import get_app_resource
from models import AppModel,Studio,Log
import re

   
def update_studio_appset(name):
    """
    reside appinfo in database,which belong to this studio
    
    @name: str: studio name
    """
    print('update studio : %s'%name)
    studio = Studio.objects.get(name=name) 
    appinfos = AppInfoBuilder.get_apps(name)
    try:
        app_objs=[]
        for appinfo in appinfos:
            app,c =AppModel.objects.get_or_create(sku=appinfo.sku)
            app_objs.append(app)
            
        for app in studio.appmodel_set.all():
            if app not in app_objs:
                app.status='deactive'
                app.save()
                
        app_names=[appinfo.name for appinfo in app_objs if appinfo.name]
        
        for appinfo,app in zip(appinfos,app_objs):
            appinfo.update_resource()
            transfer(appinfo, app, studio)
        studio.status.done_update_appset()
    except UserWarning as e:
        print(str(e))
        studio.status.done_update_appset(str(e))
    

def update_app(sku,studio_name):
    studio=Studio.objects.get(name=studio_name)
    info = AppInfoBuilder(sku=sku)
    info.update_info()
    info.update_meta()
    info.update_resource()
    
    app,c= AppModel.objects.get_or_create(sku=sku)
    transfer(info, app, studio)
      
def transfer(info,app,studio):
    """
    transfer info to a appModel object
    """
    if not app.name:
        app_names=[row.name for row in studio.appmodel_set.all()]
        app.name=info.adapt_name(app_names)

    info.name=app.name    # 针对 数据库已经保存了 name的情况，例如人员修改的name
    info.update_status()
    
    print('update app : %s'%app.name)
    app.__dict__.update(info.__dict__)
    app.studio=studio
    app.screenshots = ';'.join(info.screenshots)
    app.save()
    
    l=Log(category='app.update',key=info.sku,type=app.status,title='update app {sku}'.format(sku=info.sku),content=info.get_msg())
    l.save()        


class AppInfoBuilder(object):
    """
    get app infomation from pts and ps,then process the name and judge app status
     
    **Note** this method should be used only for update AppModel
    
    instance method call order:
    
    appinfo = AppInfoBuilder(sku)
    appinfo.update_info()
    |   appinfo.update_meta()
    |   appinfo.update_resource()
    |   appinfo.adapt_name(name_list)
    |   |   appinfo.update_status()
    
    
    static method call order:
    
    appinfos = AppInfoBuilder.get_apps(name)
    for appinfo in appinfos:
        appinfo.update_resource()
        appinfo.update_status()
    
    """
    def __init__(self,sku):
        self.sku=sku
        
        self.name=''
        self.long_dsp=''
        self.short_dsp=''
        self.pub_name=''
        self.gp_link=''
        self.last_meta=True
        self.bundle_id=''
        
        self.media_url=''
        
        self.icon=''
        self.fea_graph=''
        self.screenshots=[]
        
        self._msg=[]
        self._error=[]
        self._deative=False

    
    def adapt_name(self,exist_names):
        """
        改造 pub_name,最后显示为 app_path_name
        
        @names: list: other app names in the same studio
        """
        if not self.pub_name:
            self.pub_name=''
            
        if  re.search(r'[^\x00-\xff]',self.pub_name):
            name= self.bundle_id.split('.')[-1].lstrip('android_')
        else:
            name= re.sub('\W+','-',self.pub_name)
            
        org_name=name
        index=0
        while name and name in exist_names:
            name=org_name+'_%s'%index
            index+=1
            
        self.name=name
        if not self.name:
            self._error.append('not found valid name')
        return name
    
    def get_msg(self):
        if self._error:
            return ';'.join(self._error)
        else:
            return ';'.join(self._msg)
     
    def update_resource(self):
        """
        利用media_url从网盘获取资源地址。
        注意：要先从获取media_url
        """
        resource= get_app_resource(self.media_url)
        self._check_msg_resource(resource)
        self.icon=resource.get('icon')
        self.fea_graph=resource.get('fea_graph')
        self.screenshots=resource.get('screenshots')
        self.orientation=resource.get('orientation')
        

    def update_status(self):
        if self._deative:
            self.status='deactive'
        elif self._error:
            self.status ='error'
        else:
            for msg in self._msg:
                if msg.find('try to use previous version')!=-1:
                    self.status ='warning'
                    return
            self.status = 'normal'
            self._msg.append('update information success')

        
    def update_info(self):
        """
        更新app的
            'sku':app.prd_id,
            'app_code':app.prj_code,
            'pub_name':app.appextrainfo.pub_name,
            'media_url'
            'gp_link'
            
        最好使用静态函数 update_apps_info批量更新信息
        
        **Note** 由于PTS中，appextrainfo.pub_name 暂时是空值，所以pub_name取之于ps系统的metainfo.title
        """
        pts=PTS()
        info_dc= pts.get_app_info(self.sku)
        self._check_msg_pts(info_dc)
        self.__dict__.update(info_dc)
    
    def update_meta(self):
        ps=PS()
        app_dc= ps.get_app_meta(self.sku)
        self._check_msg_ps(app_dc)
        self.__dict__.update(app_dc)      
        
    def _check_msg_pts(self,app_dc):
        if not app_dc.get('media_url'):
            self._error.append('not found media url')
        if not app_dc.get('gp_link'):
            self._error.append('not found google play link')  
        if 'msg' in app_dc and app_dc.get('msg')=='app should not appear in APG':
            self._deative =True
       
    def _check_msg_ps(self,app_dc):
        if 'error' in app_dc:
            self._error.append(app_dc.pop('error'))
        elif 'msg' in app_dc:
            self._msg.append(app_dc.pop('msg'))
    
    def _check_msg_resource(self,app_dc):
        if not app_dc.get('icon'):
            self._error.append('not found app icon')
        if not app_dc.get('fea_graph'):
            self._error.append('not found feature graphic')
        if not app_dc.get('screenshots'):
            self._error.append('not found screenshots')        
    
    @staticmethod
    def get_apps(studio_name):
        appinfos = AppInfoBuilder._get_apps_from_pts(studio_name)
        AppInfoBuilder._get_metas_from_ps(appinfos)
        return appinfos
    

    @staticmethod
    def _get_apps_from_pts(studio_name):
        pts= PTS()
        apps = pts.get_apps(studio_name)
        out =[]
        for app_dc in apps:
            app=AppInfoBuilder(app_dc.get('sku'))
            app._check_msg_pts(app_dc)
            app.__dict__.update(app_dc)
            out.append(app)
             
        return out
    
    @staticmethod
    def _get_metas_from_ps(apps):
        """
        从ps系统批量获取app.metainfo
        """
        ps=PS()
        apps_sku=[app.sku for app in apps]
        apps_dc=ps.get_apps_meta(apps_sku)
        for app in apps:
            app_dc = apps_dc.get(app.sku)
            app._check_msg_ps(app_dc)
            app.__dict__.update(app_dc)
    

            